//
//  OosServiceEntryParser.m
//  oos4ios
//
//  Created by Pablo Gonzalez on 4/13/11.
//  Copyright 2011 11870.com. All rights reserved.
//

#import "OosServiceEntryParser.h"
#import <oos4ios/Model/OosService.h>
#import <oos4ios/Oos4ios.h>
#import "../Utils/OosEnum+Internal.h"
#import "OosLocationParser.h"
#import "OosReviewEntryParser.h"
#import "../Atom/Feeds/OosServiceFeed.h"
#import "../Atom/Feeds/OosFeed.h"
#import "../Atom/Entries/OosServiceEntry.h"
#import "../GData/Common/Elements/GDataTextConstruct.h"
#import "../GData/Common/Elements/GDataDateTime.h"
#import "../Constants/OosNamespaces.h"
#import <oos4ios/Model/OosAvatarImage.h>
#import <oos4ios/Model/OosOffer.h>
#import <oos4ios/Model/OosTag.h>
#import <oos4ios/Model/OosList.h>
#import <oos4ios/Model/OosUserList.h>
#import <oos4ios/Model/OosUserTag.h>

@implementation OosServiceEntryParser

static OosServiceEntryParser *instance;

+ (OosServiceEntryParser *)instance
{
    if (!instance) {
        instance = [[OosServiceEntryParser alloc] init];
    }
    return instance;
}

- (id) parseEntry: (OosEntry *) entry
{
    if ([entry isKindOfClass:[NSError class]]) {
        NSError *error = (NSError *)entry;
        NSLog(@"Error caught: %@", [error localizedDescription]);
        return nil;
    }
    OosServiceEntry *serviceEntry = (OosServiceEntry *) entry;
    OosService *service = [OosService serviceFromSlug:[entry.slug stringValue]];
    NSString *rawTags = [serviceEntry.tags stringValue];
    NSString *rawLists = [serviceEntry.lists stringValue];
	NSDate *updatedDate = [entry.updatedDate date];
	if ([service isPreviousTo:updatedDate]) {
		// Only update the service if the publishDate is later than the one in 
		// the restored service or if it is the first time this service is 
		// created (if no updated date is present)
		OosCategory *cat;
		OosAttribute *attribute;
        
		// Populate main info
		service.name = [entry.title stringValue];
		service.reviewSnippet = [entry.summary stringValue];
		
		NSArray *categories = entry.categories;
		service.categories = nil;
		service.attributes = nil;
		
		for (GDataCategory *category in categories) {
			NSString *scheme = category.scheme;
			if ([scheme hasSuffix: @"privacy"]) {
				// Handle privacy
				service.privacy = category.term;
			} 
//            else if ([scheme hasSuffix: @"categories"]) {
//				// Handle categories
//				cat = [OosCategory categoryFromTerm:category.term];
//				cat.label = category.label;
//				[service.categories addObject: cat];
//			} else if ([scheme hasSuffix: @"attributes"]) {
//				// Handle attributes
//				attribute = [OosAttribute attributeFromTerm:category.term];
//				attribute.label = category.label;
//				[service.attributes addObject: attribute];
//			}
			// TODO: handle user lists and tags (need to pass the user slug)
		}
        
        // service tags
        if (rawTags != nil) {
            service.tags = rawTags;
        }
        
        if (rawLists != nil) {
            service.lists = rawLists;
        }
		
		NSArray *links = entry.links;
		// Iterate links in the entry
		for (GDataLink *link in links) {
			NSString *rel = link.rel;
			if ([rel isEqualToString: @"alternate"]) {
				service.permalink = link.href;
			} else if ([rel isEqualToString: @"service"]) {
				service.serviceUrlString = link.href;
			} else if ([rel isEqualToString: @"media"]) {
				service.mediaUrlString = link.href;
			}
		}
		if ([serviceEntry isKindOfClass:[OosServiceEntry class]]) {
            service.oosId = [serviceEntry.oosId stringValue];
            service.urlString = [serviceEntry.url stringValue];
            service.reviewCount = [serviceEntry.reviewsCounter intNumberValue];
            service.savedCount = [serviceEntry.savedCounter intNumberValue];
            service.rating = [serviceEntry.rating numberValue];
            service.leadServiceUrlString = [serviceEntry.leadService stringValue];
            service.telephone = [serviceEntry.telephone stringValue];
            service.updated = updatedDate;
        }
		service.location = [[OosLocationParser instance] 
							parseLocationFromService:serviceEntry];
        
        NSString *userSlug = entry.author.slug;
        if (userSlug) {
            OosUser *user = [OosUser userFromSlug:userSlug];
            [user.mutableServices addObject:service];
            [service.mutableUsers addObject:user];
//            OosReview *review = [[OosReviewEntryParser instance] parseEntry:entry];
//            review.service = service;
//            review.author = user; 
//            [user.mutableReviews addObject:review];
            
//            OosMe *me = [OosMe me];
//            if (me != nil && [me.slug isEqualToString:userSlug]) {
//                service.myReview = review;
//            }
            
//            // process and register tags:
//            NSMutableSet *reviewTags = review.mutableTags;
//            NSMutableSet *userTags = user.mutableTags;
//            for (NSString *term in [service.tags componentsSeparatedByString:@","]) {
//                OosTag *tag = [OosTag tagFromTerm:term];
//                [reviewTags addObject:tag];
//                [userTags addObject:tag];
//                [OosUserTag userTagFromTag: tag 
//                                   andUser: user];
//            }
//            
//            // process and register lists:
//            NSMutableSet *reviewLists = review.mutableLists;
//            NSMutableSet *userLists = user.mutableLists;
//            for (NSString *term in [service.lists componentsSeparatedByString:@","]) {
//                OosList *list = [OosList listFromTerm:term];
//                [reviewLists addObject: list];
//                [userLists addObject: list];
//                [OosUserList userListFromList: list 
//                                      andUser: user];
//            }
        }
        
        // process saved by
        OosSavedBy *savedBy = serviceEntry.savedBy;
        if (savedBy) {
            for (SavedByUser *savedByUser in savedBy.users) {
                OosUser *user = [OosUser userFromSlug:savedByUser.slug];
                user.avatar = [OosAvatarImage avatarFromPath: savedByUser.avatarUrl];
                [service addSavedByObject: user];
//                [service.savedBy addObject:user];
            }
        }
	}
    // this is outside of core data
    if (serviceEntry.offer) {
        OosOfferElement *offerElement = serviceEntry.offer;
        OosOffer *offer = [OosOffer offer];
        offer.offerId = offerElement.oosId.stringValue;
        offer.title = offerElement.title.stringValue;
        offer.summary = offerElement.summary.stringValue;
        offer.value = offerElement.value.stringValue;
        service.offer = offer;
    } else {
        service.offer = nil;
    }
    NSError *error = nil;
    [service.managedObjectContext save: &error];
    if (error) {
        NSLog(@"Error saving just parsed Service: %@", [error localizedDescription]);
    }
	return service;
}

static NSString *schemeTemplate = @"http://api.11870.com/api/v2/%@/%@";

- (OosEntry *) reverseParseEntry: (OosObject *) object {
//    OosMe *me = [Oos4ios instance].me;
    OosServiceEntry *entry = [OosServiceEntry entry];
    [entry setNamespaces:[OosNamespaces defaultNamespace]];
    // If we have given an review object then add the details to the entry
    // and replace with the service
    if ([object isKindOfClass:[OosReview class]]) {
        return [[OosReviewEntryParser instance] reverseParseEntry:object];
    }
    [self reverseParseObject:object intoEntry:entry];
    return entry;
}

- (void) reverseParseObject: (OosObject*) object intoEntry: (OosEntry*)entry {
    if (![object isKindOfClass:[OosService class]]) {
        [NSException raise:@"Unsupported type" 
                    format:@"Expected object of class %@", [OosService className]];
    }
    if (![entry isKindOfClass:[OosServiceEntry class]]) {
        [NSException raise:@"Unsupported type" 
                    format:@"Expected object of class %@", 
         NSStringFromClass([OosServiceEntry class])];
    }
    
    OosService* service = (OosService*)object;
    OosServiceEntry* serviceEntry = (OosServiceEntry*)entry;
    
    NSMutableDictionary *namespaces = [NSMutableDictionary dictionary];
    [namespaces setValue:OOS_NAMESPACE forKey:OOS_PREFIX];
    [namespaces setValue:GEORSS_NAMESPACE forKey:GEORSS_PREFIX];
    [namespaces setValue:GML_NAMESPACE forKey:GML_PREFIX];
    [serviceEntry addNamespaces:namespaces];
    
    serviceEntry.identifier = @"http://11870.com";
    serviceEntry.title = [GDataAtomTitle textConstructWithString:service.name];
    serviceEntry.slug = [OosSlug valueWithString:service.slug];
    serviceEntry.url = [OosUrl valueWithString:service.urlString];
    serviceEntry.telephone = [OosTelephone valueWithString:service.telephone];
    serviceEntry.oosId = [OosId valueWithString:service.oosId];
    serviceEntry.reviewsCounter = [OosReviewCounter valueWithNumber:service.reviewCount];
    serviceEntry.savedCounter = [OosSavedCounter valueWithNumber:service.savedCount];
    serviceEntry.rating = [[OosRating new] autorelease];
    serviceEntry.rating.numberValue = service.rating;
    serviceEntry.updatedDate = [GDataDateTime dateTimeWithDate:[NSDate date] timeZone:nil];
    
    // Parse location
    [[OosLocationParser instance] reverseParseLocation:service.location intoEntry:serviceEntry];
}


@end
